package toubiao.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.sound.midi.MidiDevice.Info;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import dao.ConditionFilterFactory;
import dao.domain.ConditionFilterClass;
import spring.SpringContextHolder;
import toubiao.dao.BaseDaoI;
import toubiao.dao.business.ProjectDaoI;
import toubiao.dao.impl.mysql.business.ProjectDaoImpl;
import toubiao.domain.excel.ProjectGrid4Excel;
import toubiao.domain.po.business.PoContract;
import toubiao.domain.po.business.PoProject;
import toubiao.domain.vo.assist.PageHelper;
import toubiao.domain.vo.business.ContractGrid;
import toubiao.domain.vo.business.ProjectGrid;
import toubiao.domain.vo.easyUi.DataGrid;
import toubiao.exception.CustomException;
import toubiao.utility.ProApplicationContext;
import toubiao.utils.Dictionary;
import toubiao.utils.ProUtilConfig;
import toubiao.utils.ProUtilExcel;
import toubiao.utils.ProUtilLogger;
import toubiao.utils.ProUtilPoConvert;
import static toubiao.utils.ProUtilLogger.rootLogger;
import toubiao.utils.excel.domain.ExcelModel;
import toubiao.utils.filter.Convert;
import toubiao.utils.filter.FilterCondition;
import toubiao.utils.filter.HqlBuilder;
import toubiao.utils.filter.OrderCondition;
import utils.UtilCollection;
import utils.UtilController;
import utils.UtilJackson;
import utils.UtilString;
import utils.UtilUuid;
import utils.easyui.domain.EzDatagrid;

@Service
public class DataGridServiceImpl {
	//@Autowired
	//private ProjectDaoI dao;
	private Logger logger=ProUtilLogger.rootLogger;
	
	    /**
	    * @Title: getDataGridByConditions
	    * @Description: 根据 条件生成 Hql语句，包含where 和 order ，其中 hqlId= xxxGridList 和  hqlId = xxxGridCount 需要成对出现, 未dataGrid页面使用
	    * @param @param objectName
	    * @param @param filterConditionList
	    * @param @param orderConditionList
	    * @param @param ph
	    * @param @return
	    * @param @throws ClassNotFoundException
	    * @param @throws InstantiationException
	    * @param @throws IllegalAccessException
	    * @param @throws CustomException    
	    * @return DataGrid    
	    * @throws
	    */
	public <T> DataGrid getDataGridByConditions(String objectName,List<FilterCondition> filterConditionList, List<OrderCondition> orderConditionList,PageHelper ph) throws ClassNotFoundException, InstantiationException, IllegalAccessException, CustomException {
		
		//组合成 Hql id 以便在hql.xml 文件中 找到相应的 Hql 语句
		String listHql=getHql(objectName, "GridList");
		String countHql=getHql(objectName, "GridCount");
		
		Convert convert=Dictionary.HQL_COMMON_CONVERT;
		
		ProUtilLogger.rootLogger.info(objectName);
		
		DataGrid dg = new DataGrid();
		rootLogger.info(objectName);
		rootLogger.info(listHql);
		rootLogger.info(countHql);
		
		String simpleClassNameOfPo="Po"+objectName;
		String simpleClassNameOfGrid=objectName+"Grid";
		
		Class sourceClass=Class.forName(Dictionary.getFullClassName(simpleClassNameOfPo));
		Class targetClass=Class.forName(Dictionary.getFullClassName(simpleClassNameOfGrid));
		
		List<T> list=getPoByCondition(sourceClass, listHql, objectName, convert, filterConditionList, orderConditionList, ph);
		List<T> countList=getPoByCondition(sourceClass, countHql, objectName, convert, filterConditionList, orderConditionList);
		
		//List<ProjectGrid> gridList=ProUtilPoVoConvert.getVoListOfProjectGrid(list);
		
		List gridList=ProUtilPoConvert.getList(sourceClass, targetClass, list);
		rootLogger.info(gridList.size()+"");
		
		dg.setRows(gridList);
		dg.setTotal(Long.valueOf(countList.size()));
		String jsonString=UtilJackson.me().object2Json(dg);
		rootLogger.info(jsonString);
		
		return dg;
	}
	
	
	
	
	public <T> List<T> getPoAll(Class<T> clazz,String objectName) throws CustomException {
		String hql=getHql(objectName, "GridList");
		BaseDaoI<T> dao=ProApplicationContext.getDao(objectName);
		List<T> list=dao.find(hql);
		return list;
	}
	
	public <T> List<T> getPoByIds(Class<T> clazz,String objectName,String ids) throws CustomException {
		List<T> list=new ArrayList<>();
		String[] idArray=ids.split(",");
		if(idArray==null || idArray.length==0){
			throw new CustomException("ids is error");
		}
		BaseDaoI<T> dao=ProApplicationContext.getDao(objectName);
		for(String id:idArray){
			T t=dao.get(clazz, Long.parseLong(id));
			list.add(t);
		}
		return list;
	}
	
	public <T> List<T>  getPoByCondition (Class<T> clazz,String hql,String objectName,
			Convert convert,List<FilterCondition> filterConditionList, List<OrderCondition> orderConditionList) throws CustomException{
		return getPoByCondition(clazz, hql, objectName, convert, filterConditionList, orderConditionList,null);
	}
	
	public <T> List<T>  getPoByCondition (Class<T> clazz,String hql,String objectName,
			Convert convert,List<FilterCondition> filterConditionList, List<OrderCondition> orderConditionList,
			PageHelper ph) throws CustomException{
		BaseDaoI<T> dao=ProApplicationContext.getDao(objectName);
		rootLogger.info(dao+"");
		rootLogger.info(hql+"");
		String hqlWithCondition=HqlBuilder.buildHql(hql, convert, filterConditionList, orderConditionList);
		List<T> list=null;
		rootLogger.info(hqlWithCondition);
		if(ph==null){
			list=dao.find(hqlWithCondition);
		}else{
			list=dao.find(hqlWithCondition, ph.getPage(), ph.getRows());
		}
		return list;
	}
	
	public String getHql(String objectName,String hqlSuffix){
		String hqlKey=objectName+hqlSuffix;
		String hqlString=Dictionary.HQL_MAP.get(hqlKey);
		return hqlString;
	}
	
	 
	public <S,T>String creatExcelFile(Class<S> sourceClass,Class<T> targetClass,List<S> sList,String excelModelId) throws IOException, InstantiationException, IllegalAccessException{
		List<T> tList=ProUtilPoConvert.getList(sourceClass, targetClass, sList);
		String fileAbsPath=ProUtilConfig.getDownloadTempPath()+"/"+UtilUuid.getUuidString()+".xlsx";
		ExcelModel excelModel=Dictionary.EXCEL_MODEL_MAP.get(excelModelId);
		ProUtilExcel.list2ExcelFile(fileAbsPath, tList, excelModel);
		return fileAbsPath;
	}
	
	public String downloadFileAll(String objectName,String fileType) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, CustomException{
		return downloadFileByIds(objectName, fileType, null);
	}
	
	public String downloadFileByIds(String objectName,String fileType,String ids) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException, CustomException{
		Class sourceClass=Class.forName(Dictionary.getFullClassName("po"+objectName));
		Class targetClass=Class.forName(Dictionary.getFullClassName(objectName+"Grid4Excel"));
		List list=null;
		if(ids==null){
			list=getPoAll(sourceClass, objectName);
		}else {
			list=getPoByIds(sourceClass, objectName, ids);
		}
		String fileAbsPath=null;
		if(fileType.trim().equalsIgnoreCase("excel")){
			fileAbsPath=creatExcelFile(sourceClass, targetClass, list, objectName+"Grid");
			return fileAbsPath;
		}
		throw new RuntimeException("fileType is error.");
	}
	
	
	public String downloadFileByCondition(String objectName,String fileType,List<FilterCondition> filterConditionList, List<OrderCondition> orderConditionList) throws InstantiationException, IllegalAccessException, IOException, ClassNotFoundException, CustomException{
		Class sourceClass=Class.forName(Dictionary.getFullClassName("po"+objectName));
		Class targetClass=Class.forName(Dictionary.getFullClassName(objectName+"Grid4Excel"));
		String listHql=getHql(objectName, "GridList");
		Convert convert=Dictionary.HQL_COMMON_CONVERT;
		List list=getPoByCondition(sourceClass, listHql, objectName, convert, filterConditionList, orderConditionList);
		String fileAbsPath=null;
		if(fileType.trim().equalsIgnoreCase("excel")){
			fileAbsPath=creatExcelFile(sourceClass, targetClass, list, objectName+"Grid");
			return fileAbsPath;
		}
		throw new RuntimeException("fileType is error.");
	}




	/**
	 * @param filterClass 生成 查询中的 条件语句
	 * @param ph pageHelp
	 * @param className 根据此查找BaseHql 和 dao
	 * @return
	 * @throws CustomException 
	 * @throws IllegalAccessException 
	 * @throws InstantiationException 
	 */
	public EzDatagrid getDataGridForLdtdSelectByConditionFilter(
			ConditionFilterClass filterClass, PageHelper ph,String className) throws CustomException, InstantiationException, IllegalAccessException {
		// TODO Auto-generated method stub
		EzDatagrid datagrid=new EzDatagrid<>();
		datagrid.setTotal(0L);
		datagrid.setRows(new ArrayList<>());
		
		if(UtilString.isNullOrEmpty(className)){
			return datagrid;
		}
		
		String listHqlId=className+"_list_ldrdSelectDlg";
		String countHqlId=className+"_count_ldrdSelectDlg";
		String baseHql=Dictionary.HQL_MAP.get(listHqlId);// 需包含 where 1=1 
		
		String countHql=Dictionary.HQL_MAP.get(countHqlId);
		
		if(UtilString.isNullOrEmpty(baseHql)){
			throw new RuntimeException("根据 className 找不到 对应的 baseHql 语句");
		}
		
		String queryListHql=null;
		String queryCountHql=null;
		
		String filterHql=ConditionFilterFactory.buildHql(filterClass, null);
		if(UtilString.isNullOrEmpty(filterHql)){
			queryListHql=baseHql;
			queryCountHql=countHql;
		}else{
			queryListHql=baseHql+filterHql;
			queryCountHql=countHql+filterHql;
		}
		
		ProUtilLogger.rootLogger.info("queryListHql = "+queryListHql);
		ProUtilLogger.rootLogger.info("queryCountHql = "+queryCountHql);
		
		BaseDaoI dao=ProApplicationContext.getDao(className);
		List poList=dao.find(queryListHql, ph.getPage(), ph.getRows());
		
		Class sourceClass=null;
		Class targetClass=null;
		
		if(className.trim().equalsIgnoreCase("contract")){
			sourceClass=PoContract.class;
			targetClass=ContractGrid.class;
		}
		List voList=ProUtilPoConvert.getList(sourceClass, targetClass, poList);
		
		
		//get count
		Long count=dao.count(queryCountHql);
		logger.info(count+"");
		datagrid.setRows(voList);
		datagrid.setTotal(count);
		
		return datagrid;
	}




}
